package com.glink.manage.controller;

import com.glink.common.contants.ErrorCode;
import com.glink.common.exception.AbstractErrorException;
import com.glink.common.util.LogUtil;
import com.glink.common.vo.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

/**
 * @ClassName:AbstractBaseController
 * @Author: qiushaoshan
 * @Date: 2025-01-07
 * @Version: V1.0
 * @Description Controller基类
 **/
@Controller
@Slf4j
public class AbstractBaseController {

    public static final String X_REFRESH_TOKEN = "X-REFRESH-TOKEN";
    public static final String X_COMPANY_NO = "X-COMPANY-NO";

    @Autowired
    protected HttpServletRequest request;

    @Autowired
    protected MessageSource messageSource;
    
//    @Autowired
//    private EmpService empService;
//    @Autowired
//    private EmpDeptRService empDeptRService;



//    protected String getCurrentEmp() {
//        String authorization = request.getHeader(AUTHORIZATION);
//        Objects.requireNonNull(authorization, "获取请求头Authorization失败");
//        Emp currentEmp = empService.getCurrentEmp(authorization);
//        Objects.requireNonNull(currentEmp, "该员工不存在");
//        return currentEmp.getEmpId();
//    }
//
//    protected String getDeptId() {
//        String companyNo = getCompanyNo(true);
//        String emp = getCurrentEmp();
//        Dept dept = empDeptRService.findDeptByEmpId(emp, companyNo);
//        return dept.getDeptId();
//    }

    protected <E> ResponseResult<E> response(String code, String codeInfo, E object) {
        return new ResponseResult<>(code, object, codeInfo);
    }

    protected <E> ResponseResult<E> response(E object) {
        return new ResponseResult<>(ErrorCode.REQ_SUCCESS.getValue(), object, ErrorCode.REQ_SUCCESS.getDesc());
    }

    protected <E> ResponseResult<E> responseError(E object) {
        return new ResponseResult<>(ErrorCode.API_REQUEST_FAILED.getValue(), object, ErrorCode.API_REQUEST_FAILED.getDesc());
    }

    protected <T> ResponseResult<T> responseTokenError() {
        return new ResponseResult<>(ErrorCode.TOKEN_ERROR.getValue(), null, ErrorCode.TOKEN_ERROR.getDesc());
    }

    protected <T> ResponseResult<T> responseRefreshTokenError() {
        return new ResponseResult<>(ErrorCode.REFRESH_TOKEN_ERROR.getValue(), null, ErrorCode.REFRESH_TOKEN_ERROR.getDesc());
    }

    protected <E> ResponseResult<E> failure(String message, E object) {
        return new ResponseResult<>(ErrorCode.API_REQUEST_FAILED.getValue(), object, ErrorCode.API_REQUEST_FAILED.getDesc());
    }

    /**
     * 通用处理异常,
     * 包括带数据和不带数据通用的
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {AbstractErrorException.class})
    @ResponseBody
    public ResponseEntity<ResponseResult<String>> handleAbstractException(AbstractErrorException e) {
        e.printStackTrace();
        log.error("错误消息 参数 {}", LogUtil.encode(e));
        log.error("错误消息", e);
        StringBuilder msg;
        try {
            if (e.getErrorDetails() == null || e.getErrorDetails().length == 0) {
                msg = new StringBuilder(messageSource.getMessage(e.getErrorCode(), null, judeLocale(e.getLan())));
            } else {
                msg = new StringBuilder(messageSource.getMessage(e.getErrorCode(), e.getErrorDetails(), judeLocale(e.getLan())));
            }

            log.error("错误消息内容{}", LogUtil.encode(msg.toString()));

        }catch (NoSuchMessageException ne){
            log.error("错误消息 获取properties未找到：{}", e.getErrorCode());
            msg = new StringBuilder();
            if(Objects.nonNull(e.getErrorDetails())){
                for (String errorDetail : e.getErrorDetails()) {
                    msg.append(errorDetail);
                }
            }else{
                msg = new StringBuilder(e.getMessage());
            }
        }
        log.error("错误消息内容{}", LogUtil.encode(msg));
        ResponseResult<String> responseResult = new ResponseResult<String>(e.getErrorCode(), msg.toString());
        MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
        headers.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        return new ResponseEntity<>(responseResult, headers, HttpStatus.OK);
    }

    protected Locale judeLocale(String lan) {
        return new Locale("zh", "CN");
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public ResponseEntity<ResponseResult<String>> handleValidationException(MethodArgumentNotValidException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        StringBuffer stringBuffer = new StringBuffer();
        for (ObjectError s : errors) {
            // 异常信息不显示属性字段
//            Object[] obj = s.getArguments();
//            DefaultMessageSourceResolvable resolvable = (DefaultMessageSourceResolvable) obj[0];
//            stringBuffer.append(resolvable.getDefaultMessage()).append(" ").append(s.getDefaultMessage()).append(", ");
            stringBuffer.append(s.getDefaultMessage()).append(", ");
        }
        String errorMsg = null;
        if (stringBuffer.toString().length() > 2) {
            errorMsg = stringBuffer.toString().substring(0, stringBuffer.toString().length() - 2);
        }
        ResponseResult<String> responseResult = new ResponseResult("100002", errorMsg);
        return new ResponseEntity(responseResult, HttpStatus.OK);
    }

    @ExceptionHandler({Exception.class})
    @ResponseBody
    public ResponseEntity<ResponseResult<String>> handleException(Exception e) {
        log.error("Exception {}", LogUtil.encode(e));
        log.error("Exception", e);
        if(e.getMessage().contains("validation")){
            // 处理form表单提交，抛出的异常
            String[] split = e.getMessage().split("default message", -1);
            if(split.length > 0 && !StringUtils.isEmpty(split[0])){
                String errorMsg = split[split.length - 1];
                ResponseResult<String> responseResult = new ResponseResult("100002", errorMsg);
                return new ResponseEntity(responseResult, HttpStatus.OK);
            }
        }else if(e.getMessage().contains("jdbc.exception")){
            ResponseResult<String> responseResult = new ResponseResult("200001", e.getMessage());
            return new ResponseEntity(responseResult, HttpStatus.OK);
        }else if(e.getMessage().contains("SQLException")){
            ResponseResult<String> responseResult = new ResponseResult("200001", "数据库操作失败");
            return new ResponseEntity(responseResult, HttpStatus.OK);
        }else if(e.getMessage().contains("java.sql.SQL") || e.getMessage().contains("Data truncation")){
            ResponseResult<String> responseResult = new ResponseResult("200001", "数据库操作失败");
            return new ResponseEntity(responseResult, HttpStatus.OK);
        }
        String msg = this.messageSource.getMessage("300001", null, Locale.getDefault());
        ResponseResult<String> responseResult = new ResponseResult("300001", msg);
        return new ResponseEntity(responseResult, HttpStatus.OK);
    }

    @ExceptionHandler({HttpMessageNotReadableException.class})
    @ResponseBody
    public ResponseEntity<ResponseResult<String>> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        e.printStackTrace();
        log.error("HttpMessageNotReadableException {}", LogUtil.encode(e));
        log.error("HttpMessageNotReadableException", e);
        String msg = this.messageSource.getMessage("100002", null, Locale.getDefault());
        ResponseResult<String> responseResult = new ResponseResult("100002", msg);
        return new ResponseEntity(responseResult, HttpStatus.OK);
    }

    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    @ResponseBody
    public ResponseEntity<ResponseResult<String>> handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        e.printStackTrace();
        log.error("HttpMediaTypeNotSupportedException", e);
        log.error("HttpMediaTypeNotSupportedException {}", LogUtil.encode(e));
        ResponseResult<String> responseResult = new ResponseResult("300001", e.getMessage());
        return new ResponseEntity(responseResult, HttpStatus.OK);
    }
}
